﻿namespace CV.Dal.Mongo.Tools
{
    using CV.Entities.Tools;
    using CV.Interfaces.Dal;
    using MongoDB.Bson.Serialization;
    using MongoDB.Driver;
    using MongoDB.Driver.Builders;
    using System;
    using System.Collections.Generic;
    using System.Linq;

    public abstract class BaseAO<T, TId> : IBaseAO<T, TId>
        where T : IEntity<TId>
        where TId : IEquatable<TId>
    {
        private CVMongoClient client;
        private string tableName;

        public BaseAO(CVMongoClient client, string tableName)
        {
            this.tableName = tableName;
            this.client = client;

            if (!BsonClassMap.IsClassMapRegistered(typeof(T)))
            {
                BsonClassMap.RegisterClassMap<T>(cm => MapEntity(cm));
            }
        }

        protected abstract void MapEntity(BsonClassMap<T> cm);

        public MongoCollection<T> GetCollection()
        {
            var server = client.GetServer();
            var dbName = client.ConfigurationWrapper.AppSettings["DBName"];
            var users = server.GetDatabase(dbName);

            return users.GetCollection<T>(tableName);
        }

        public virtual T GetById(TId id)
        {
            return GetCollection().Find(Query<T>.EQ(x => x.Id, id)).FirstOrDefault();
        }

        public virtual T Create(T item)
        {
            var result = GetCollection().Insert(item);
            return item;
        }

        public virtual void Delete(TId id)
        {
            GetCollection().Remove(Query<T>.EQ(x => x.Id, id), RemoveFlags.Single);
        }

        public virtual void Update(T item)
        {
            GetCollection().Update(Query<T>.EQ(x => x.Id, item.Id), Update<T>.Replace(item));
        }

        public virtual IEnumerable<T> ListAll()
        {
            return GetCollection().FindAll();
        }
    }
}
